package redisclient

import (
	"gitee.com/lsy007/redisclient/model"
	"github.com/pquerna/ffjson/ffjson"
)

// BLPop(timeout int64, keys ...string) ([]string,err error)
// BRPop(timeout int64, keys ...string) ([]string,err error)
// BRPopLPush(source, destination string, timeout int64) (string,err error)
// LIndex(key string, index int64) (string,err error)
// LInsertBefore(key, pivot, value string) (int64,err error)
// LInsertAfter(key, pivot, value string) (int64,err error)
// LLen(key string) (int64,err error)
// LPop(key string) (string,err error)
// LPush(key string, values ...string) (int64,err error)
// LPushX(key string, values ...string) (int64,err error)
// LRange(key string, start, end int64) ([]string,err error)
// LRem(key string, count int64, value string) (int64,err error)
// LSet(key string, index int64, value string) (string,err error)
// LTrim(key string, start, end int64) (string,err error)
// RPop(key string) (string,err error)
// RPopLPush(source, destination string) (string,err error)
// RPush(key string, values ...string) (int64,err error)
// RPushX(key string, values ...string) (int64,err error)

// 移出并获取多个列表的第一个元素， 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
func (c *RedisClient) BLPop(timeout int64, key string) (values []string, err error) {
	args := &model.RedisArgsModel{Keys: []string{key}, Time: timeout}
	response, err = c.Request("BLPop", "List", args)
	return response.StringSlice, err
}

// 移出并获取列表的最后一个元素， 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
func (c *RedisClient) BRPop(timeout int64, key string) (values []string, err error) {
	args := &model.RedisArgsModel{Keys: []string{key}, Time: timeout}
	response, err = c.Request("BRPop", "List", args)
	return response.StringSlice, err
}

// 从列表中弹出一个值，将弹出的元素插入到另外一个列表中并返回它； 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
func (c *RedisClient) BRPopLPush(source, destination string, timeout int64) (value string, err error) {
	args := &model.RedisArgsModel{Source: source, Destination: destination, Time: timeout}
	response, err = c.Request("BRPopLPush", "List", args)
	return response.String, err
}

// 通过索引获取列表中的元素
func (c *RedisClient) LIndex(key string, index int64) (value string, err error) {
	args := &model.RedisArgsModel{Key: key, Index: index}
	response, err = c.Request("LIndex", "List", args)
	return response.String, err
}

// 在指定列表的元素前插入元素
func (c *RedisClient) LInsertBefore(key, pivot, value string) (index int64, err error) {
	args := &model.RedisArgsModel{Key: key, Pivot: pivot, Value: value}
	response, err = c.Request("LInsertBefore", "List", args)
	return response.Int, err
}

// 在指定列表的元素后插入元素
func (c *RedisClient) LInsertAfter(key, pivot, value string) (index int64, err error) {
	args := &model.RedisArgsModel{Key: key, Pivot: pivot, Value: value}
	response, err = c.Request("LInsertAfter", "List", args)
	return response.Int, err
}

// 获取列表长度
func (c *RedisClient) LLen(key string) (len int64, err error) {
	args := &model.RedisArgsModel{Key: key}
	response, err = c.Request("LLen", "List", args)
	return response.Int, err
}

// 移出并获取列表的第一个元素，返回值为移除的元素
func (c *RedisClient) LPop(key string) (value string, err error) {
	args := &model.RedisArgsModel{Key: key}
	response, err = c.Request("LPop", "List", args)
	return response.String, err
}

// 将一个或多个值插入到列表头部
func (c *RedisClient) LPush(key string, values ...interface{}) (count int64, err error) {
	var bytes []byte
	if bytes, err = ffjson.Marshal(values); err != nil {
		return
	}
	args := &model.RedisArgsModel{Key: key, Bytes: bytes}
	response, err = c.Request("LPush", "List", args)
	return response.Int, err
}

// 将一个或多个值插入到已存在的列表头部
func (c *RedisClient) LPushX(key string, values ...interface{}) (count int64, err error) {
	var bytes []byte
	if bytes, err = ffjson.Marshal(values); err != nil {
		return
	}
	args := &model.RedisArgsModel{Key: key, Bytes: bytes}
	response, err = c.Request("LPushX", "List", args)
	return response.Int, err
}

// 获取列表指定索引范围内的元素
func (c *RedisClient) LRange(key string, start, end int64) (values []string, err error) {
	args := &model.RedisArgsModel{Key: key, StartInt: start, EndInt: end}
	response, err = c.Request("LRange", "List", args)
	return response.StringSlice, err
}

// 移除列表元素，根据参数 COUNT 的值，移除列表中与参数 VALUE 相等的元素
func (c *RedisClient) LRem(key string, count int64, value string) (index int64, err error) {
	args := &model.RedisArgsModel{Key: key, Count: count, Value: value}
	response, err = c.Request("LRem", "List", args)
	return response.Int, err
}

// 通过索引设置列表元素的值
func (c *RedisClient) LSet(key string, index int64, value string) (status string, err error) {
	args := &model.RedisArgsModel{Key: key, Index: index, Value: value}
	response, err = c.Request("LSet", "List", args)
	return response.String, err
}

// 对一个列表进行修剪(trim)，就是说，让列表只保留指定区间内的元素，不在指定区间之内的元素都将被删
func (c *RedisClient) LTrim(key string, start, end int64) (status string, err error) {
	args := &model.RedisArgsModel{Key: key, StartInt: start, EndInt: end}
	response, err = c.Request("LTrim", "List", args)
	return response.String, err
}

// 移除列表的最后一个元素，返回值为移除的元素
func (c *RedisClient) RPop(key string) (value string, err error) {
	args := &model.RedisArgsModel{Key: key}
	response, err = c.Request("RPop", "List", args)
	return response.String, err
}

// 移除列表的最后一个元素，并将该元素添加到另一个列表并返回
func (c *RedisClient) RPopLPush(source, destination string) (value string, err error) {
	args := &model.RedisArgsModel{Source: source, Destination: destination}
	response, err = c.Request("RPopLPush", "List", args)
	return response.String, err
}

// 将一个或多个值插入到列表尾部
func (c *RedisClient) RPush(key string, values ...interface{}) (index int64, err error) {
	var bytes []byte
	if bytes, err = ffjson.Marshal(values); err != nil {
		return
	}
	args := &model.RedisArgsModel{Key: key, Bytes: bytes}
	response, err = c.Request("RPush", "List", args)
	return response.Int, err
}

// 将一个或多个值插入到已存在的列表尾部
func (c *RedisClient) RPushX(key string, values ...interface{}) (index int64, err error) {
	var bytes []byte
	if bytes, err = ffjson.Marshal(values); err != nil {
		return
	}
	args := &model.RedisArgsModel{Key: key, Bytes: bytes}
	response, err = c.Request("RPushX", "List", args)
	return response.Int, err
}
